from ctypes import c_bool
from datetime import datetime
from multiprocessing import shared_memory, Value
import cv2
import numpy as np
from src.utils.logger import logger_instance as log

class CameraBroadcaster:
    def __init__(self, camera_info):
        self.height = camera_info.get('height', 720)
        self.width = camera_info.get('width', 1280)
        self.fps = camera_info.get('fps', 30)
        self.stop_sign = Value(c_bool, False)
        self.frame = shared_memory.SharedMemory(create=True, size=np.zeros(shape=(self.height, self.width, 3),
                                                                           dtype=np.uint8).nbytes)
        self.memory_name = self.frame.name

    def run(self):
        # 尝试不同的摄像头索引
        for index in [1, 0, 2, 4]:
            cap = cv2.VideoCapture(index)
            if cap.isOpened():
                log.info(f"Camera opened at index {index}")
                break
            cap.release()
        else:
            log.error("No camera found at any index")
            return
    
        # 设置摄像头参数
        cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'))
        cap.set(cv2.CAP_PROP_FRAME_WIDTH, self.width)
        cap.set(cv2.CAP_PROP_FRAME_HEIGHT, self.height)
        cap.set(cv2.CAP_PROP_FPS, self.fps)
    
        # 检查实际分辨率
        actual_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
        actual_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
        if actual_width != self.width or actual_height != self.height:
            log.warning(f"Resolution mismatch: requested {self.width}x{self.height}, got {actual_width}x{actual_height}")
    
        sender = np.ndarray((self.height, self.width, 3), dtype=np.uint8, buffer=self.frame.buf)
    
        try:
            while True:
                if self.stop_sign.value:
                    break
    
                ret, frame = cap.read()
                if not ret:
                    log.error("Failed to read frame")
                    continue
    
                if frame.shape != sender.shape:
                    log.warning(f"Frame shape mismatch: expected {sender.shape}, got {frame.shape}")
                    continue
    
                try:
                    sender[:] = frame[:]
                except Exception as e:
                    log.error(f"Shared memory write failed: {e}")
                    break
    
        except (KeyboardInterrupt, SystemExit):
            log.info('Camera broadcaster closing')
        finally:
            cap.release()
            if hasattr(self, 'frame') and self.frame:
                self.frame.close()
                self.frame.unlink()